import type { AxiosError, AxiosInstance, AxiosResponse } from 'axios';
import axios from 'axios';
import { useEnv } from '/@/hooks/useEnv';
import { ResultEnum, ContentTypeEnum } from '/@/enums/httpEnum';
import { getToken } from '/@/stores/auth';
import { showErrorMessage, showHttpErrorMessage } from './msg';
import { showLoading, hideLoading } from './loading';
import { fileDownload, fileImport } from './other';
import { AxiosRetry } from './retry';
import { clearAuthInfo } from '/@/stores/auth';
import router from '/@/router';

interface axiosConfig {
	retryCount?: number;
	isRetry?: boolean;
	loading?: false;
	isDownload?: boolean;
	isImport?: boolean;
	callback?: Function;
}

const defaultConfig: axiosConfig = {
	isRetry: false, // 是否支持重试
	retryCount: 3, // 重试次数
	loading: false, // 是否下显示加载中
	isDownload: false, // 是否文件流下载
	isImport: false, // 是否导入文件
	callback: null, // 回调函数
};

const { VITE_API_URL } = useEnv();

const service: AxiosInstance = axios.create({
	baseURL: VITE_API_URL + '/admin/',
	timeout: 30 * 1000, // 请求超时时间
	headers: { 'Content-Type': ContentTypeEnum.JSON },
});

service.interceptors.request.use((config: any) => {
	const { loading } = config.requestOptions;
	const token = getToken();
	if (token) config.headers.Authorization = token;
	if (loading) showLoading();
	return config;
});

service.interceptors.response.use(
	(response: AxiosResponse) => {
		const data = response.data;
		// window.console.log(data);
		if (data.code === ResultEnum.SUCCESS) {
			return data.data;
		} else {
			showErrorMessage(data);

			// 检验token过期重新登录
			if (data.code === ResultEnum.EXPIRE) {
				clearAuthInfo();
				router.push('/login');
			}
			return Promise.reject(data);
		}
	},
	(err) => {
		// window.console.log(err);
		// 接口异常重试机制
		const { isRetry, retryCount } = err.config.requestOptions;
		if (isRetry && (err.config._retryCount || 0) < retryCount) {
			const axiosRetry = new AxiosRetry();
			axiosRetry.retry(service, err);
			return;
		}
		showHttpErrorMessage(err);
		return Promise.reject(err.response);
	}
);

const request = {
	get<T = any>(url: string, data?: any, config?: axiosConfig): Promise<T> {
		return request.request('GET', url, { params: data }, config);
	},
	post<T = any>(url: string, data?: any, config?: axiosConfig): Promise<T> {
		return request.request('POST', url, { data }, config);
	},
	put<T = any>(url: string, data?: any, config?: axiosConfig): Promise<T> {
		return request.request('PUT', url, { data }, config);
	},
	delete<T = any>(url: string, data?: any, config?: axiosConfig): Promise<T> {
		return request.request('DELETE', url, { params: data }, config);
	},
	request<T = any>(method = 'GET', url: string, data?: any, config?: axiosConfig): Promise<T> {
		const options = Object.assign({}, defaultConfig, config);

		return new Promise((resolve, reject) => {
			const api_url = VITE_API_URL?VITE_API_URL:(window.location.protocol + '//' + window.location.host);
			if (options.isDownload) {
				fileDownload(method, api_url + '/admin' + url, getToken(), data?.params ? data.params : data, config.callback, resolve, reject);
			} else if (options.isImport) {
				fileImport(api_url + '/admin' + url, getToken(), data?.data ? data.data : data, config.callback, resolve, reject);
			} else {
				service({ method, url, ...data, requestOptions: options })
					.then((res) => {
						resolve(res as unknown as Promise<T>);
					})
					.catch((e: Error | AxiosError) => {
						reject(e);
					})
					.finally(() => {
						if (options.loading) hideLoading();
					});
			}
		});
	},
};

export default request;
